package com.excilys.training.ebanking.web.controllers;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.excilys.training.ebanking.iservice.IDateProvider;
import org.excilys.training.ebanking.iservice.IDateProviderFactory;
import org.excilys.training.ebanking.iservice.IServiceCompte;
import org.excilys.training.ebanking.iservice.IServiceOperation;
import org.excilys.training.ebanking.model.Compte;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.excilys.training.ebanking.web.java.ComptePersonnalise;
import com.excilys.training.ebanking.web.java.TransfertDataOperation;
import com.excilys.training.ebanking.web.java.TransfertDataOperation.Builder;
import com.excilys.training.ebanking.web.security.UtilisateurPersonnalise;

@Controller
@RequestMapping("/client")
public class UserController {

	static final Logger logger = LoggerFactory.getLogger(UserController.class);
	@Autowired
	IServiceCompte serviceCompte;

	@Autowired
	IServiceOperation serviceOperation;

	@Autowired
	IDateProviderFactory dateProviderFactory;

	@RequestMapping("/accueil.html")
	public ModelAndView redirectUtilisateur(ModelMap model) {
		UtilisateurPersonnalise utilisateur = (UtilisateurPersonnalise) SecurityContextHolder
				.getContext().getAuthentication().getPrincipal();

		List<Compte> listCompte = serviceCompte.getAllAccountById(utilisateur
				.getId());
		List<ComptePersonnalise> listeComptePerso = new ArrayList<ComptePersonnalise>();

		for (Compte compte : listCompte) {
			double soldefutur = serviceCompte.getSoldePrevisonnel(compte
					.getId());
			ComptePersonnalise cp = new ComptePersonnalise.Builder()
					.withId(compte.getId())
					.withNomCompte(compte.getNomCompte())
					.withSoldeCourant(compte.getSoldeCourant())
					.withEncour(compte.getEncour())
					.withSoldePrevisionnel(soldefutur).build();
			listeComptePerso.add(cp);
		}

		model.addAttribute("comptesPerso", listeComptePerso);
		model.addAttribute("comptes", listCompte);
		model.addAttribute("nickname", utilisateur.getUsername());

		return new ModelAndView("/client/accueil");
	}

	@RequestMapping("/compte/{id}")
	public String initGoToDetailCompte(@PathVariable("id") int id,
			ModelMap model, HttpSession session) {

		logger.debug("Initialisation n°1 des liste d operation");

		session.setAttribute("stat2", "classe_cache");

		int moisCourant = new DateTime().getMonthOfYear();
		int anneeCourante = new DateTime().getYear();
		IDateProvider dateProvider = dateProviderFactory
				.createDateProvider(moisCourant);

		int nombresOperationsparPage = serviceOperation
				.getNombreOperationsByList();

		Builder builderDataOperation = new TransfertDataOperation.Builder()
				.withListMois(dateProvider.getListMois())
				.withListAnnee(dateProvider.getListAnnee())
				.withCompte(serviceCompte.getAccount(id))
				.withMontantOperationsCarte(
						serviceOperation.getMontantOperationsCarteByMonth(id,
								moisCourant, anneeCourante))
				.withNombreOperationSansCarte(
						serviceOperation.getNombreOperationsWithoutCard(id,
								moisCourant, anneeCourante))
				.withNombreOperationCarte(
						serviceOperation.getNombreOperationsCard(id,
								moisCourant, anneeCourante))
				.withOperationsCarte(
						serviceOperation.getSomeCardOperations(id, moisCourant,
								anneeCourante, 0))
				.withOperationsSansCarte(
						serviceOperation.getSomeNoCardOperations(id,
								moisCourant, anneeCourante, 0));

		TransfertDataOperation dataOpeataion = builderDataOperation.build();

		model.addAttribute("selectedMonth", moisCourant);
		model.addAttribute("selectedYear", anneeCourante);
		model.addAttribute("calendrier", dataOpeataion.getListmois());
		model.addAttribute("calendrierAnnee", dataOpeataion.getListannee());
		model.addAttribute("compte", dataOpeataion.getCompte());
		model.addAttribute("totalcartes",
				dataOpeataion.getMontantOperationsCarte());
		model.addAttribute("operationsSansCarte",
				dataOpeataion.getOperationsSansCarte());
		model.addAttribute("operationsCarte",
				dataOpeataion.getOperationsCarte());
		model.addAttribute("hasOperationsSansCarte",
				dataOpeataion.getHasOperationsSansCarte());
		model.addAttribute("hasOperationsCarte",
				dataOpeataion.getHasOperationsCarte());
		model.addAttribute("nbPages",
				dataOpeataion.getNombrePage(nombresOperationsparPage));
		model.addAttribute("nombrePagesForCard",
				dataOpeataion.getNombrePageCarte(nombresOperationsparPage));
		model.addAttribute("numeroPageCarte", 1);
		model.addAttribute("numeroPage", 1);

		return "/client/detail_compte";
	}

	@RequestMapping("/compte/operationsCarte/{mois}/{year}/{id}/{numerolien}/{numeroLienCarte}")
	public String fromPaginationToDetailCompte(@PathVariable("id") int id,
			@PathVariable("mois") int mois, @PathVariable("year") int year,
			@PathVariable("numerolien") int numerolien,
			@PathVariable("numeroLienCarte") int numeroLienCarte, ModelMap model) {
		logger.debug("pagination: selection du lien n" + numerolien);

		int nombresOperationsparPage = serviceOperation
				.getNombreOperationsByList();
		int firstLine = (numerolien - 1) * nombresOperationsparPage;
		int firstLineCard = (numeroLienCarte - 1) * nombresOperationsparPage;

		IDateProvider dateProvider = dateProviderFactory
				.createDateProvider(mois);

		Builder builderDataOperation = new TransfertDataOperation.Builder()
				.withListMois(dateProvider.getListMois())
				.withListAnnee(dateProvider.getListAnnee())
				.withCompte(serviceCompte.getAccount(id))
				.withMontantOperationsCarte(
						serviceOperation.getMontantOperationsCarteByMonth(id,
								mois, year))
				.withNombreOperationSansCarte(
						serviceOperation.getNombreOperationsWithoutCard(id,
								mois, year))
				.withNombreOperationCarte(
						serviceOperation
								.getNombreOperationsCard(id, mois, year))
				.withOperationsCarte(
						serviceOperation.getSomeCardOperations(id, mois, year,
								firstLineCard))
				.withOperationsSansCarte(
						serviceOperation.getSomeNoCardOperations(id, mois,
								year, firstLine));

		TransfertDataOperation dataOpeataion = builderDataOperation.build();

		model.addAttribute("selectedMonth", mois);
		model.addAttribute("selectedYear", year);
		model.addAttribute("calendrier", dataOpeataion.getListmois());
		model.addAttribute("calendrierAnnee", dataOpeataion.getListannee());
		model.addAttribute("compte", dataOpeataion.getCompte());
		model.addAttribute("totalcartes",
				dataOpeataion.getMontantOperationsCarte());
		model.addAttribute("operationsSansCarte",
				dataOpeataion.getOperationsSansCarte());
		model.addAttribute("operationsCarte",
				dataOpeataion.getOperationsCarte());
		model.addAttribute("hasOperationsSansCarte",
				dataOpeataion.getHasOperationsSansCarte());
		model.addAttribute("hasOperationsCarte",
				dataOpeataion.getHasOperationsCarte());
		model.addAttribute("nbPages",
				dataOpeataion.getNombrePage(nombresOperationsparPage));
		model.addAttribute("nombrePagesForCard",
				dataOpeataion.getNombrePageCarte(nombresOperationsparPage));
		model.addAttribute("numeroPageCarte", numeroLienCarte);
		model.addAttribute("numeroPage", numerolien);

		return "/client/detail_compte";

	}

	@RequestMapping(value = "/compte/{id}/selection.html", method = RequestMethod.POST)
	public String redirectCompteDetailAnneMois(HttpServletRequest request,
			@PathVariable("id") int id, ModelMap model) {
		String mois = request.getParameter("moisChoisi");
		int moisInt = Integer.parseInt(mois);
		String annee = request.getParameter("anneeChoisie");
		int anneeInt = Integer.parseInt(annee);
		return new String("redirect:/client/compte/" + id + "/" + moisInt + "/"
				+ anneeInt + ".html");
	}

	/**
	 * Controleur permettant de gerer les changements de mois/annees a partir du
	 * formulaire
	 * 
	 * @param id
	 *            (l'id du compte) & request (Valeur du forulaire mois/annees)
	 * 
	 * @param model
	 * @return
	 */

	@RequestMapping("/compte/{id}/{month}/{annee}")
	public String goToDetailYearAndMonthSelected(@PathVariable("id") int id,
			@PathVariable("month") int mois, @PathVariable("annee") int year,
			ModelMap model) {
		logger.debug("initialisation des opérations suivant la date et l'annee");

		IDateProvider dateProvider = dateProviderFactory
				.createDateProvider(mois);

		int nombresOperationsparPage = serviceOperation
				.getNombreOperationsByList();

		Builder builderDataOperation = new TransfertDataOperation.Builder()
				.withListMois(dateProvider.getListMois())
				.withListAnnee(dateProvider.getListAnnee())
				.withCompte(serviceCompte.getAccount(id))
				.withMontantOperationsCarte(
						serviceOperation.getMontantOperationsCarteByMonth(id,
								mois, year))
				.withNombreOperationSansCarte(
						serviceOperation.getNombreOperationsWithoutCard(id,
								mois, year))
				.withNombreOperationCarte(
						serviceOperation
								.getNombreOperationsCard(id, mois, year))
				.withOperationsCarte(
						serviceOperation.getSomeCardOperations(id, mois, year,
								0))
				.withOperationsSansCarte(
						serviceOperation.getSomeNoCardOperations(id, mois,
								year, 0));

		TransfertDataOperation dataOpeataion = builderDataOperation.build();

		model.addAttribute("selectedMonth", mois);
		model.addAttribute("selectedYear", year);
		model.addAttribute("calendrier", dataOpeataion.getListmois());
		model.addAttribute("calendrierAnnee", dataOpeataion.getListannee());
		model.addAttribute("compte", dataOpeataion.getCompte());
		model.addAttribute("totalcartes",
				dataOpeataion.getMontantOperationsCarte());
		model.addAttribute("operationsSansCarte",
				dataOpeataion.getOperationsSansCarte());
		model.addAttribute("operationsCarte",
				dataOpeataion.getOperationsCarte());
		model.addAttribute("hasOperationsSansCarte",
				dataOpeataion.getHasOperationsSansCarte());
		model.addAttribute("hasOperationsCarte",
				dataOpeataion.getHasOperationsCarte());
		model.addAttribute("nbPages",
				dataOpeataion.getNombrePage(nombresOperationsparPage));
		model.addAttribute("nombrePagesForCard",
				dataOpeataion.getNombrePageCarte(nombresOperationsparPage));
		model.addAttribute("numeroPageCarte", 1);
		model.addAttribute("numeroPage", 1);
		logger.debug(" fin d'initialisation");

		return "/client/detail_compte";
	}

	@RequestMapping("/compte/{id}/mois")
	public String recordDataForExcel(
			@RequestParam(value = "valeurMois", required = false) int month,
			@RequestParam(value = "valeurAnnee", required = false) int annee,
			@PathVariable("id") int id, ModelMap mp) throws Exception {

		int mois = month;
		int year = annee;
		return "redirect:/client/compte/" + id + "/" + mois + "/" + year
				+ "/liste_Operations.xls";
	}

	@RequestMapping("/compte/update")
	public String updateState(HttpServletRequest request, HttpSession session) {
		session.removeAttribute("stat2");
		session.setAttribute("stat2", request.getParameter("etat"));
		return "/client/detail_compte";
	}
}
